using Entity = NtRuirun.Mes.Wms.Entities.WarehouseEntity;
using InputDto = NtRuirun.Mes.Wms.Dtos.WarehouseInputDto;

namespace NtRuirun.Mes.Wms
{
    /// <summary>
    /// 实体存储：库位信息信息
    /// </summary>
    public partial class WarehouseStore
    {
        /// <summary>
        /// 初始化一个<see cref="WarehouseStore"/>类型的新实例
        ///</summary>
        public WarehouseStore(IServiceProvider provider)
        { 
            ServiceProvider = provider;
            Logger = provider.GetLogger(GetType());
        }

        #region 属性
        /// <summary>
        /// 获取 服务提供者对象
        /// </summary>
        protected IServiceProvider ServiceProvider { get; }

        /// <summary>
        /// 获取 日志对象
        ///</summary>
        protected ILogger Logger { get; }

        /// <summary>
        /// 获取 事件总线
        ///</summary>
        protected IEventBus EventBus => ServiceProvider.GetService<IEventBus>();

        /// <summary>
        /// 获取 实体仓储模型
        ///</summary>
        protected IRepository<Entity, Guid> EntityRepository => ServiceProvider.GetService<IRepository<Entity, Guid>>();

        /// <summary>
        /// 获取 实体查询数据集
        /// </summary>
        public virtual IQueryable<Entity> Entities => EntityRepository.Query();

        #endregion

        #region Entity
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="entities">数据实体</param>
        /// <returns></returns>
        public OperationResult Insert(params Entity[] entities)
        {
            Check.NotNull(entities, nameof(entities));

            var result = EntityRepository.Insert(entities);
            if (result.Succeeded)
            {
                EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Insert) { Entities = entities.ToList() };
                EventBus?.Publish(eventData);
            }
            return result;
        }

        /// <summary>
        /// 异步新增
        /// </summary>
        /// <param name="entities">数据实体</param>
        /// <returns></returns>
        public async Task<OperationResult> InsertAsync(params Entity[] entities)
        {
            Check.NotNull(entities, nameof(entities));

            var result = await EntityRepository.InsertAsync(entities);
            if (result.Succeeded)
            {
                EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Insert) { Entities = entities.ToList() };
                await EventBus?.PublishAsync(eventData);
            }
            return result;
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="entities">数据实体</param>
        /// <returns></returns>
        public OperationResult Update(params Entity[] entities)
        {
            Check.NotNull(entities, nameof(entities));

            var result = EntityRepository.Update(entities);
            if (result.Succeeded)
            {
                EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Update) { Entities = entities.ToList() };
                EventBus?.Publish(eventData);
            }
            return result;
        }

        /// <summary>
        /// 异步更新
        /// </summary>
        /// <param name="entities">数据实体</param>
        /// <returns></returns>
        public async Task<OperationResult> UpdateAsync(params Entity[] entities)
        {
            Check.NotNull(entities, nameof(entities));

            EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Update);
            var result = OperationResult.Success();
            foreach (var entity in entities)
            {
                Check.ValidateKey(entity.Id, nameof(entity.Id));

                var dbEntity = EntityRepository.Get(entity.Id);
                if (dbEntity == null)
                {
                    return new OperationResult(OperationResultType.Forbidden, $"编号为“{entity.Id}”的 {nameof(Entity)} 不存在。");
                }
                result = await EntityRepository.UpdateAsync(entity);
                if (!result.Succeeded)
                {
                    return result;
                }
                eventData.Entities.Add(entity);
            }
            if (eventData.HasData())
            {
                await EventBus?.PublishAsync(eventData);
            }
            return result;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="entities">数据实体</param>
        /// <returns></returns>
        public OperationResult Delete(params Entity[] entities)
        {
            Check.NotNull(entities, nameof(entities));

            var result = EntityRepository.Delete(entities);
            if (result.Succeeded)
            {
                //触发事件
                EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Delete) { Entities = entities.ToList() };
                EventBus?.Publish(eventData);
            }
            return result;
        }

        /// <summary>
        /// 异步删除
        /// </summary>
        /// <param name="keys">数据实体编号</param>
        /// <returns></returns>
        public async Task<OperationResult> DeleteAsync(Guid[] keys)
        {
            Check.NotNull(keys, nameof(keys));

            EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Delete);
            var result = OperationResult.Success();
            foreach (var key in keys)
            {
                Check.ValidateKey(key, nameof(key));

                var entity = EntityRepository.Get(key);
                if (entity == null)
                {
                    return new OperationResult(OperationResultType.Forbidden, $"编号为“{key}”的 {nameof(Entity)} 不存在。");
                }
                result = await EntityRepository.DeleteAsync(entity);
                if (!result.Succeeded)
                {
                    return result;
                }
                eventData.Entities.Add(entity);
            }
            if (eventData.HasData())
            {
                await EventBus?.PublishAsync(eventData);
            }
            return result;
        }
        #endregion

        #region Dtos
        /// <summary>
        /// 异步以DTO为载体新增
        /// </summary>
        /// <param name="dtos">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> InsertByDtoAsync(params InputDto[] dtos)
        {
            Check.NotNull(dtos, nameof(dtos));
            Check.Validate<InputDto, Guid>(dtos, nameof(dtos));

            EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Insert);
            OperationResult result = await EntityRepository.InsertAsync(dtos, null,
                async (dto, entity) =>
                {
                    eventData.Entities.Add(entity);
                    return await Task.FromResult(entity);
                });
            if (result.Succeeded)
            {
                if (eventData.HasData())
                {
                    await EventBus?.PublishAsync(eventData);
                }
            }
            return result;
        }

        /// <summary>
        /// 异步以DTO为载体新增
        /// </summary>
        /// <param name="dtos">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public virtual async Task<OperationResult> UpdateByDtoAsync(params InputDto[] dtos)
        {
            Check.NotNull(dtos, nameof(dtos));
            Check.Validate<InputDto, Guid>(dtos, nameof(dtos));

            EntityEventData<Entity> eventData = new(EntityRepository.DbContext, OperateType.Update);
            OperationResult result = await EntityRepository.UpdateAsync(dtos,
                async (dto, entity) =>
                {
                    Check.ValidateKey(dto.Id, nameof(dto.Id));

                    var dbEntity = EntityRepository.Get(dto.Id);
                    if (dbEntity == null)
                    {
                        result = new OperationResult(OperationResultType.Forbidden, $"编号为“{dto.Id}”的 {nameof(Entity)} 不存在。");
                    }
                    eventData.Entities.Add(entity);
                    await Task.FromResult(0);
                });
            if (result.Succeeded)
            {
                if (eventData.HasData())
                {
                    await EventBus?.PublishAsync(eventData);
                }
            }
            return result;
        }

        #endregion

    }
}